﻿using System;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Web.Mvc;
using RedSand.Web.Security;


namespace RedSand.Web.Mvc.Controls
{
    public static class RsCaptcha
    {
        /// <summary>
        /// Tạo hình ảnh captcha và sinh mã tương ứng
        /// </summary>
        /// <param name="helper">Html</param>
        /// <param name="name">Input field name</param>
        /// <param name="with">Chiều rộng hình ảnh</param>
        /// <param name="height">Chiều cao hình ảnh</param>
        /// <param name="textLength">Độ dài mã captcha</param>
        /// <returns></returns>
        public static MvcHtmlString Captcha(this HtmlHelper helper, string name, int with, int height, int textLength)
        {
            return Captcha(helper, name, with, height, textLength, null, null, null, null, false);
        }
        /// <summary>
        /// Tạo hình ảnh captcha và sinh mã tương ứng
        /// </summary>
        /// <param name="helper">Html</param>
        /// <param name="name">Input field name</param>
        /// <param name="with">Chiều rộng hình ảnh</param>
        /// <param name="height">Chiều cao hình ảnh</param>
        /// <param name="textLength">Độ dài mã captcha</param>
        /// <param name="fontFamily">Font</param>
        /// <param name="textColor">Màu chữ</param>
        /// <param name="backColor">Màu nền</param>
        /// <param name="brushColor">Kiểu tô nền</param>
        /// <param name="addNoise">Thêm nhiễu (muỗi)</param>
        /// <returns></returns>
        public static MvcHtmlString Captcha(this HtmlHelper helper, string name, int with, int height, int textLength, string fontFamily, string textColor, string backColor, string brushColor, bool addNoise)
        {
            return GenerateImage(name, with, height, textLength, fontFamily, textColor, backColor, brushColor, addNoise);
        }
        /// <summary>
        /// Tạo hình ảnh captcha và sinh mã tương ứng
        /// </summary>
        /// <typeparam name="TModel">Model class</typeparam>
        /// <typeparam name="TValue">Value type</typeparam>
        /// <param name="helper">Html</param>
        /// <param name="name">Input field name</param>
        /// <param name="with">Chiều rộng hình ảnh</param>
        /// <param name="height">Chiều cao hình ảnh</param>
        /// <param name="textLength">Độ dài mã captcha</param>
        /// <returns></returns>
        public static MvcHtmlString CaptchaFor<TModel,TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, int with, int height, int textLength)
        {
            return CaptchaFor(helper,expression,with,height,textLength, null, null, null, null, false);
        }
        /// <summary>
        /// Tạo hình ảnh captcha và sinh mã tương ứng
        /// </summary>
        /// <typeparam name="TModel">Model class</typeparam>
        /// <typeparam name="TValue">Value type</typeparam>
        /// <param name="helper">Html</param>
        /// <param name="name">Input field name</param>
        /// <param name="with">Chiều rộng hình ảnh</param>
        /// <param name="height">Chiều cao hình ảnh</param>
        /// <param name="textLength">Độ dài mã captcha</param>
        /// <param name="fontFamily">Font</param>
        /// <param name="textColor">Màu chữ</param>
        /// <param name="backColor">Màu nền</param>
        /// <param name="brushColor">Kiểu tô nền</param>
        /// <param name="addNoise">Thêm nhiễu (muỗi)</param>
        /// <returns></returns>
        public static MvcHtmlString CaptchaFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, int with, int height, int textLength, string fontFamily, string textColor, string backColor, string brushColor, bool addNoise)
        {
            string name = "CaptchaCode";
            if (expression.Body.NodeType == ExpressionType.MemberAccess)
            {
                name = (expression.Body as MemberExpression).Member.Name;
            }
            return GenerateImage(expression.Name, with, height, textLength, fontFamily, textColor, backColor, brushColor, addNoise);
        }
        /// <summary>
        /// Kiểm tra tính đúng đắn của mã captcha
        /// </summary>
        /// <param name="CaptcharCode">Mã captcha được sinh ra(mã hóa)</param>
        /// <param name="Captcha">Mã captcha được nhập vào</param>
        /// <param name="ignoreCase">Phiên biệt chữ hoa chữ thường</param>
        /// <returns>true nếu trùng khớp, false nếu ngược lại</returns>
        public static bool IsVaild(string CaptcharCode, string Captcha, bool ignoreCase)
        {
            return string.Compare(CaptcharCode, RsEncryption.TripleDESEncrypt(RsKey.CaptchaKey, Captcha), ignoreCase) == 0;
        }

        //private
        private static MvcHtmlString GenerateImage(string name, int with, int height, int textLength, string fontFamily, string textColor, string backColor, string brushColor, bool addNoise)
        {
            if (string.IsNullOrWhiteSpace(name)) name = "CaptchaCode";
            string code = GetRandomCode(textLength);
            string html = "";
            html += "<img src='/RedSand/CaptchaImage?code=" + code + "&width=" + with + "&height=" + height + "&fontFamily=" + fontFamily + "&addNoise=" + addNoise + "&textColor=" + textColor + "&backColor=" + backColor + "&brushColor=" + brushColor + "'/>";
            html += "<input type='hidden' name='" + name + "' value='" + code + "'/>";
            return MvcHtmlString.Create(html);
        }
        private static string GetRandomCode(int length)
        {
            string chars = "abcdefghijklmnopqrstuvxwyzABCDEFGHIJKLMNOPQRSTUVXWYZ0123456789";
            string text, result;
            Random rnd = new Random();
            do
            {
                text = "";
                for (int i = 0; i < length; i++)
                {
                    text += chars[rnd.Next(0, 62)];
                }
                result = RsEncryption.TripleDESEncrypt(RsKey.CaptchaKey, text);
            }
            while (result.Contains("+"));
            return result;
        }
    }
}
